﻿//===========================================================================================================================
// The C'Quare Project - http://www.peacequare.com/cquare.aspx
// Copyright (c) 2009
// by Peacequare® - Amir Moussa
//===========================================================================================================================
// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 
// as published by the Free Software Foundation, either version 3 of the License, or any later version.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// This program is distributed in the hope that it will be useful.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//===========================================================================================================================

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Linq;
using System.Windows.Forms;

using P2.SimpleAccounting.Modules.FiAccount.DAL;
using P2.SimpleAccounting.Modules.FiAccount.Services;

using P2.Framework.BOLBase;
using P2.Framework.Helper;
using P2.Framework.Helper.Configuration;
using System.ComponentModel;
using System.Transactions;

namespace P2.SimpleAccounting.Modules.FiAccount.BusinessEntities
{
    public class FiAccountModel : BizObject
    {
        public override int ObjectID
        {
            get
            {
                return 1701;
            }
        }

        #region "Constructors"
        // add new Instance
        public FiAccountModel()
        {
            //InitializeValidation();
            Modified = false;
        }


        //open an exsiting Instance
        public FiAccountModel(int keyFiAccountID)
        {
            this._fiAccountID = keyFiAccountID;
            //InitializeValidation();
            FillMyObject();
            Modified = false;
        }

        public FiAccountModel(DAL.FiAccount account)
        {
            //InitializeValidation();
            Load(account);
        }
        #endregion


        #region Members


        int _fiAccountID = -1;
        public int FiAccountID
        {
            get { return _fiAccountID; }
            protected set
            {
                if (_fiAccountID != value)
                {
                    _fiAccountID = value;
                }
            }
        }



        string _fiAccountNo = String.Empty;
        public string FiAccountNo
        {
            get { return _fiAccountNo; }
            set
            {
                if (_fiAccountNo != value)
                {
                    _fiAccountNo = value;
                    Modified = true;
                }
            }
        }

        int _fiAccountFiscalYearID = -1;
        public int FiAccountFiscalYearID
        {
            get { return _fiAccountFiscalYearID; }
            set
            {
                if (_fiAccountFiscalYearID != value)
                {
                    _fiAccountFiscalYearID = value;
                    Modified = true;
                }
            }
        }
        public FiFiscalYear FiscalYear
        {
            get
            {

                return FiFiscalYear.GetItem(this.FiAccountFiscalYearID);
            }
        }


        byte? _fiAccountLevel = null;
        public byte? FiAccountLevel
        {
            get { return _fiAccountLevel; }
            set
            {
                if (_fiAccountLevel != value)
                {
                    _fiAccountLevel = value;
                    Modified = true;
                }
            }
        }


        string _fiAccountNameEn = String.Empty;
        public string FiAccountNameEn
        {
            get { return _fiAccountNameEn; }
            set
            {
                if (_fiAccountNameEn != value)
                {
                    _fiAccountNameEn = value;
                    Modified = true;
                }
            }
        }

        string _fiAccountNameDe = String.Empty;
        public string FiAccountNameDe
        {
            get { return _fiAccountNameDe; }
            set
            {
                if (_fiAccountNameDe != value)
                {
                    _fiAccountNameDe = value;
                    Modified = true;
                }
            }
        }

        string _fiAccountNameAr = String.Empty;
        public string FiAccountNameAr
        {
            get { return _fiAccountNameAr; }
            set
            {
                if (_fiAccountNameAr != value)
                {
                    _fiAccountNameAr = value;
                    Modified = true;
                }
            }
        }

        int _parentFiAccountID = -1;
        public int ParentFiAccountID
        {
            get { return _parentFiAccountID; }
            set
            {
                if (_parentFiAccountID != value)
                {
                    _parentFiAccountID = value;
                    Modified = true;
                }
            }
        }

        int _sortingPosition = -1;
        public int SortingPosition
        {
            get { return _sortingPosition; }
            set
            {
                if (_sortingPosition != value)
                {
                    _sortingPosition = value;
                    Modified = true;
                }
            }
        }

        int _fiAccountTypeID = -1;
        public int FiAccountTypeID
        {
            get { return _fiAccountTypeID; }
            set
            {
                if (_fiAccountTypeID != value)
                {

                    _fiAccountTypeID = value;
                    Modified = true;
                }
            }
        }

        public FiAccountType AccountType
        {
            get
            {

                return FiAccountType.GetItem(this.FiAccountTypeID);

            }
        }

        bool? _chargeable = true;
        public bool? Chargeable
        {
            get { return _chargeable; }
            set
            {
                if (_chargeable != value)
                {
                    _chargeable = value;
                    Modified = true;
                }
            }
        }



        #endregion

        #region "Computed properties"
        public string FiAccountNameCur
        {
            get
            {
                switch (P2Translator.CultureLanguageFU)
                {
                    case "En":
                        {
                            return this.FiAccountNameEn;

                        }
                    case "De":
                        {
                            return this.FiAccountNameDe;

                        }
                    case "Ar":
                        {
                            return this.FiAccountNameAr;

                        }
                    default:
                        return this.FiAccountNameEn;

                }
            }
            set
            {
                switch (P2Translator.CultureLanguageFU)
                {
                    case "En":
                        {
                            this.FiAccountNameEn = value;
                            break;
                        }
                    case "De":
                        {
                            this.FiAccountNameDe = value;
                            break;
                        }
                    case "Ar":
                        {
                            this.FiAccountNameAr = value;
                            break;
                        }
                    default:
                        this.FiAccountNameEn = value;
                        break;
                }
            }

        }

        public string FiAccountFullName
        {
            get
            {
                return String.Format("{0} {1}", FiAccountNo, FiAccountNameCur);
            }
        }

        public FiAccountModel ParentFiAccount
        {
            get
            {
                if (ParentFiAccountID >= 0)
                {
                    return new FiAccountModel(ParentFiAccountID);
                }
                else
                {
                    return new FiAccountModel();
                }
            }
        }
        public string ParentFiAccountFullName
        {
            get
            {
                return this.ParentFiAccount.FiAccountFullName;
            }
        }

        public bool FiFiscalYearEditable
        {
            get
            {
                return StatusID == -1;
            }
        }

        public string FiAccountTypeName
        {
            get
            {
                if (this.AccountType != null)
                    return this.AccountType.FiAccountTypeNameCur;
                else
                    return "";
            }
        }
        public string FiAccountCategoryName
        {
            get
            {
                if (this.AccountType != null)
                    return this.AccountType.FiAccountCategoryNameCur;
                else
                    return "";
            }
        }
        public string FiAccountBalanceTypeName
        {
            get
            {
                if (this.AccountType != null)
                    return this.AccountType.FiAccountBalanceTypeNameCur;
                else
                    return "";
            }
        }
        public string FiAccountPostingTypeName
        {
            get
            {
                if (this.AccountType != null)
                    return this.AccountType.FiAccountPostingTypeNameCur;
                else
                    return "";
            }
        }


        public int FiTransactionCount
        {
            get
            {
                return DAL.FiAccountDAL.GetFiTransactionHeaderCountForAccount(this.FiAccountID);
            }
        }
        public int FiTransactionOpenCount
        {
            get
            {
                int transactionCount = 0;
                string connectionString = ConfigurationSetUp.GetConnectionString("Business");
                using (FiAccountDataModelDataContext db = new FiAccountDataModelDataContext(connectionString))
                {

                    transactionCount = FiTransactionOpenSubCount(db, this.FiAccountID);
                }
                return transactionCount;
            }
        }

        private int FiTransactionOpenSubCount(FiAccountDataModelDataContext db, int parentAccountID)
        {
            int transactionCount = db.fiGetFiTransactionHeaderCountOpenForAccount(parentAccountID).Single().TranCount.GetValueOrDefault(0);
            var subAccounts = from acc in db.FiAccounts
                              where acc.ParentFiAccountID == parentAccountID
                              select acc;
            foreach (var subAccount in subAccounts)
            {
                transactionCount += FiTransactionOpenSubCount(db, subAccount.FiAccountID);
                if (transactionCount > 0)
                    return transactionCount;
            }
            return transactionCount;
        }
        public int FiSubAccountCount
        {
            get
            {
                int accountCount = 0;
                string connectionString = ConfigurationSetUp.GetConnectionString("Business");
                using (FiAccountDataModelDataContext db = new FiAccountDataModelDataContext(connectionString))
                {

                    accountCount = (from acc in db.FiAccounts
                                    where acc.ParentFiAccountID == this.FiAccountID
                                    select acc).Count();

                }
                return accountCount;
            }
        }

        public bool IsActive
        {
            get
            {
                return (this.StatusID == 1002);
            }
        }

        #endregion

        #region "Read operations"
        //load an existing Instance
        public void Load(int keyFiAccountID)
        {
            FiAccountID = keyFiAccountID;
            if (keyFiAccountID >= 0)
            {
                FillMyObject();
            }
            else
            {
                Load(null);
            }
            Modified = false;
        }
        public void Load(DAL.FiAccount account)
        {
            
            if (account  != null)
            {
                FiAccountID = account.FiAccountID;
                FiAccountNo = account.FiAccountNo;
                FiAccountFiscalYearID = account.FiAccountFiscalYearID;
                FiAccountLevel = account.FiAccountLevel.GetValueOrDefault(1);
                FiAccountNameEn = account.FiAccountNameEn;
                FiAccountNameDe = account.FiAccountNameDe;
                FiAccountNameAr = account.FiAccountNameAr;
                ParentFiAccountID = account.ParentFiAccountID.GetValueOrDefault(-1);
                SortingPosition = account.SortingPosition.GetValueOrDefault(-1);
                FiAccountTypeID = account.FiAccountTypeID;
                Chargeable = account.Chargeable;
                StatusID = account.StatusID.GetValueOrDefault(P2.Framework.Helper.Workflows.WorkflowStatus.GetInitialStatus(-1).StatusID);
                CreatedBy = account.CreatedBy;
                EditedBy = account.EditedBy;
                this.Timestamp = account.TStamp;
            }
            else
            {
                FiAccountFiscalYearID = -1;
                FiAccountLevel = null;
                FiAccountNo = String.Empty;
                FiAccountNameEn = String.Empty;
                FiAccountNameDe = String.Empty;
                FiAccountNameAr = String.Empty;
                ParentFiAccountID = -1;
                SortingPosition = -1;
                FiAccountTypeID = -1;
                Chargeable = true;
                P2.Framework.Helper.Workflows.WorkflowStatus initStatus = P2.Framework.Helper.Workflows.WorkflowStatus.GetInitialStatus(-1);
                StatusID = initStatus.StatusID;

            }
            Modified = false;
        }
        protected P2TransactionMessage FillMyObject()
        {
            P2TransactionMessage tMsg = new P2TransactionMessage();

            if (this._fiAccountID < 0)
            {
                Load(this._fiAccountID);
                return tMsg;
            }
            



            //tMsg = base.FillMyObject();
            //if (tMsg.TransactionStatus == "green")
            //{
            try
            {
                string connectionString = ConfigurationSetUp.GetConnectionString("Business");
                using (FiAccountDataModelDataContext db = new FiAccountDataModelDataContext(connectionString))
                {
                    var accounts = from acc in db.FiAccounts
                                   where acc.FiAccountID == this._fiAccountID
                                   select acc;
                    if (accounts.Count() > 0)
                    {
                        foreach (var account in accounts)
                        {
                            Load(account);
                        }
                    }
                }


                tMsg.TransactionStatus = "green";
                tMsg.MessageText = "TMsg_FillMyObjectSuceeded";
            }
            catch (Exception ex)
            {
                tMsg.TransactionStatus = "red";
                tMsg.MessageText = "Error_Error";
                tMsg.MessageFreeText = ex.Message;
                P2ExceptionHandler.LogException(ex, this);
            }
            //}

            return tMsg;
        }

        public int GetLastChildSortingPosition()
        {
            string connectionString = ConfigurationSetUp.GetConnectionString("Business");
            using (FiAccountDataModelDataContext db = new FiAccountDataModelDataContext(connectionString))
            {
                var maxPosition = (from acc in db.FiAccounts
                                   where acc.ParentFiAccountID == this._fiAccountID
                                   select acc.SortingPosition).Max();
                return maxPosition.GetValueOrDefault(0);

            }
        }


        public static FiAccountModel GetFiAccountByAccountNo(string fiAccountNo, int fiAccountFiscalYearID)
        {
            string connectionString = ConfigurationSetUp.GetConnectionString("Business");
            using (FiAccountDataModelDataContext db = new FiAccountDataModelDataContext(connectionString))
            {

                var accounts = from acc in db.FiAccounts
                               where acc.FiAccountNo == fiAccountNo
                               && acc.FiAccountFiscalYearID == fiAccountFiscalYearID
                               select acc;

                if (accounts != null && accounts.Count() > 0)
                {
                    var account = accounts.First();
                    return new FiAccountModel(account);
                }
                else
                    return null;
            }
        }
        #endregion
        #region "Update Operations"
        public P2MessageStack InsertAndUpdate(bool checkDoublicate)
        {
            P2TransactionMessage tMsg = new P2TransactionMessage();
            //tMsg = base.InsertAndUpdate(checkDoublicate);

            tMsg.TransactionStatus = "green";
            P2MessageStack MessageStack = new P2MessageStack();


            if (tMsg.TransactionStatus == "green")
            {
                try
                {
                    //MessageStack = ValidateFieldValues();

                    if (this.FiAccountID < 0 && (FiscalYear.StatusID == 173103 || FiscalYear.StatusID == 173104))
                    {
                        MessageStack.Add(new P2TransactionMessage("red", Resources.TMsg_FiscalYearStatusError));
                    }
                    //MessageStack = P2Validation.ValidateObject("FiAccount", this);

                    foreach (P2TransactionMessage tMsgx in MessageStack)
                    {
                        if (tMsgx.TransactionStatus == "red")
                        {
                            tMsg.TransactionStatus = "red";
                            break;
                        }
                    }


                    if (tMsg.TransactionStatus == "green")
                    {
                        string connectionString = ConfigurationSetUp.GetConnectionString("Business");
                        using (FiAccountDataModelDataContext db = new FiAccountDataModelDataContext(connectionString))
                        {
                            P2.Framework.Security.AccessPermissions ap = new P2.Framework.Security.AccessPermissions();
                            if (this.StatusID == -1) this.StatusID = 1001;
                            if (this.FiAccountID < 0)
                            {
                                int? retAccountID = -1;

                                db.fiInsertFiAccount(
                                    this.FiAccountNo,
                                    this.FiAccountFiscalYearID,
                                    this.FiAccountLevel,
                                    this.FiAccountNameEn,
                                    this.FiAccountNameDe,
                                    this.FiAccountNameAr,
                                    this.ParentFiAccountID,
                                    this.SortingPosition,
                                    this.FiAccountTypeID,
                                    this.Chargeable,
                                    null,
                                    ap.UserID,
                                    this.StatusID,
                                    ref retAccountID);
                                if (retAccountID.HasValue)
                                {
                                    this.FiAccountID = retAccountID.Value;
                                    this.FillMyObject();
                                    MessageStack.Add(new P2TransactionMessage("green", Resources.TMsg_AccountAdded));
                                }
                                else
                                {
                                    MessageStack.Add(new P2TransactionMessage("red", Resources.TMsg_AccountNotUpdated));
                                }
                            }
                            else
                            {
                                int? rowsAffected = -1;
                                db.fiUpdateFiAccount(
                                    this.FiAccountNo,
                                    this.FiAccountFiscalYearID,
                                    this.FiAccountLevel,
                                    this.FiAccountNameEn,
                                    this.FiAccountNameDe,
                                    this.FiAccountNameAr,
                                    this.ParentFiAccountID,
                                    this.SortingPosition,
                                    this.FiAccountTypeID,
                                    this.Chargeable,
                                    null,
                                    this.FiAccountID,
                                    ap.UserID,
                                    this.Timestamp,
                                    this.StatusID,
                                    ref rowsAffected);
                                if (rowsAffected == 0)
                                {
                                    //(Supplier was not been updated!); //maybe because someone else changed it or because nothing was changed from here.
                                    MessageStack.Add(new P2TransactionMessage("red", Resources.TMsg_AccountNotUpdated));
                                }
                                else
                                {
                                    this.FillMyObject();
                                    MessageStack.Add(new P2TransactionMessage("green", Resources.TMsg_AccountUpdated));
                                }
                            }

                        }
                        Modified = false;
                    }



                }
                catch (Exception ex)
                {
                    //tMsg.TransactionStatus = "red";
                    //tMsg.MessageText = ex.Message;
                    MessageStack.Add(new P2TransactionMessage("red", P2.Framework.Helper.Localize.Localize.Error_Error));
                    P2ExceptionHandler.LogException(ex, this);
                }


            }
            //this.MessageStack.Add(tMsg);
            return MessageStack;
        }


        public void UpdateChargeable()
        {
            string connectionString = ConfigurationSetUp.GetConnectionString("Business");
            using (FiAccountDataModelDataContext db = new FiAccountDataModelDataContext(connectionString))
            {
                var account = (from acc in db.FiAccounts
                               where acc.FiAccountID == this._fiAccountID
                               select acc).First();
                account.Chargeable = this.Chargeable;
                db.SubmitChanges();

            }
            this.FillMyObject();
        }
        public void MoveUpDown(bool moveUp)
        {
            string connectionString = ConfigurationSetUp.GetConnectionString("Business");
            using (FiAccountDataModelDataContext db = new FiAccountDataModelDataContext(connectionString))
            {
                var accounts = from acc in db.FiAccounts
                               where acc.ParentFiAccountID == this.ParentFiAccountID
                               orderby acc.SortingPosition
                               select acc;
                DAL.FiAccount prevAccount = null, thisAccount = null, nextAccount = null;
                foreach (var account in accounts)
                {
                    if (account.FiAccountID == this._fiAccountID)
                    {
                        thisAccount = account;
                    }
                    else
                    {
                        if (thisAccount != null)
                        {
                            nextAccount = account;
                            break;
                        }
                        else
                            prevAccount = account;
                    }

                }
                if (!moveUp)
                {
                    if (thisAccount != null && nextAccount != null)
                    {
                        int? tempPos = thisAccount.SortingPosition;
                        thisAccount.SortingPosition = nextAccount.SortingPosition;
                        nextAccount.SortingPosition = tempPos;
                    }
                }
                else
                {
                    if (thisAccount != null && prevAccount != null)
                    {
                        int? tempPos = thisAccount.SortingPosition;
                        thisAccount.SortingPosition = prevAccount.SortingPosition;
                        prevAccount.SortingPosition = tempPos;
                    }
                }

                db.SubmitChanges();

            }
            this.FillMyObject();
        }

        public void Lock()
        {
            string connectionString = ConfigurationSetUp.GetConnectionString("Business");
            using (FiAccountDataModelDataContext db = new FiAccountDataModelDataContext(connectionString))
            {
                using (TransactionScope ts = new TransactionScope())
                {

                    var account = (from acc in db.FiAccounts
                                   where acc.FiAccountID == this.FiAccountID
                                   select acc).First();

                    account.StatusID = 1003;
                    LockSubAccounts(db, this.FiAccountID);
                    db.SubmitChanges();
                    ts.Complete();
                }
            }
            this.FillMyObject();
        }
        private static void LockSubAccounts(FiAccountDataModelDataContext db, int parentFiAccountID)
        {
            var accounts = from acc in db.FiAccounts
                           where acc.ParentFiAccountID == parentFiAccountID
                           select acc;
            foreach (var account in accounts)
            {
                LockSubAccounts(db, account.FiAccountID);
                account.StatusID = 1003;
            }
        }
        public bool Delete()
        {
            if (this.FiAccountID > -1)
            {
                string connectionString = ConfigurationSetUp.GetConnectionString("Business");
                using (FiAccountDataModelDataContext db = new FiAccountDataModelDataContext(connectionString))
                {
                    try
                    {


                        var account = (from acc in db.FiAccounts
                                       where acc.FiAccountID == this._fiAccountID
                                       select acc).First();
                        db.FiAccounts.DeleteOnSubmit(account);
                        db.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict);
                        return true;
                    }
                    catch (Exception)
                    {
                        return false;

                    }

                }
            }
            else
            {
                return false;
            }

        }
        #endregion

    }
}
